{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Example CV1 - Photon redirection"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This example notebook runs PennyLane's version of \"Hello world!\" for continuous-variable quantum computation, making use of the Strawberry Fields plugin. Starting with a photon in mode 0, the goal is to optimize a beamsplitter to redirect the photon to mode 1. \n",
    "\n",
    "We will compare the gradient-descent optimizer with and without momentum for this task."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Imports"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "First we need to import PennyLane. PennyLane allows us to automatically compute gradients for functions that manipulate NumPy arrays, including quantum functions. To do this, we should always *import the wrapped version of NumPy provided by PennyLane*."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pennylane as qml\n",
    "from pennylane import numpy as np\n",
    "from pennylane.optimize import GradientDescentOptimizer, MomentumOptimizer"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we create a \"device\" to run the photon redirection circuit. We use StrawberryFields to simulate a photonic quantum processor with two quantum modes (or `wires`)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "try:\n",
    "    dev = qml.device('strawberryfields.fock', wires=2, cutoff_dim=10)\n",
    "except:\n",
    "    print(\"To run this example you need to install the strawberryfields plugin...\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Quantum node\n",
    "\n",
    "We define a quantum circuit which starts with one photon into the first mode and interferes both modes on a beamsplitter. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "@qml.qnode(dev)\n",
    "def circuit(var):\n",
    "    qml.FockState(1, wires=0)\n",
    "    qml.Beamsplitter(var[0], var[1], wires=[0, 1])\n",
    "\n",
    "    return qml.expval.MeanPhoton(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Note: The `qml.qnode` decorator is a shortcut for declaring a QNode and binding it to a device. The same thing can be achieved with the code `circuit = qml.qnode.QNode(circuit, dev)`.*"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The function `circuit` uses the device `dev` to evaluate the following quantum circuit:"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"figures/redirection_circuit.png\">"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Depending on the variable $v_1$ (the transmission parameter of the beamsplitter), the photon remains in mode 0 (for $v_1 = n \\pi$ with integer $n$), gets redirected to mode 1 (for $v_2 = n\\pi / 2$), or is in a superposition of being in both modes. The phase parameter $v_2$ does not have any influence on the result, so we expect the gradient of `circuit` with respect to this parameter to be zero, and hence not get updated when we optimize the circuit."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Objective"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Next, we define a cost that quantifies whether the redirection is successful. Since we want to maximize the expectation of the photon number in mode 1, we can minimize the expectation of the photon number in mode 0 (alternatively, we could minimize the negative of the photon number in mode 1)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "def objective(var):\n",
    "    return circuit(var)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This objective has the following optimization landscape. \n",
    "\n",
    "*Note: To run the following cell you need the matplotlib library.*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline  \n",
    "from mpl_toolkits.mplot3d import Axes3D\n",
    "from matplotlib import cm\n",
    "from matplotlib.ticker import MaxNLocator\n",
    "\n",
    "fig = plt.figure(figsize = (6, 4))\n",
    "ax = fig.gca(projection='3d')\n",
    "\n",
    "X = np.arange(-3.1, 1.6, 0.1)\n",
    "Y = np.arange(-1., 1.25, 0.25)\n",
    "\n",
    "xx, yy = np.meshgrid(X, Y)\n",
    "Z = np.array([[objective([x, y]) for x in X] for y in Y]).reshape(len(Y), len(X))\n",
    "surf = ax.plot_surface(xx, yy, Z, cmap=cm.coolwarm, antialiased=False)\n",
    "\n",
    "ax.set_xlabel(\"v1\")\n",
    "ax.set_ylabel(\"v2\")\n",
    "ax.zaxis.set_major_locator(MaxNLocator(nbins = 5, prune = 'lower'))\n",
    "ax.yaxis.set_major_locator(MaxNLocator(nbins = 4, prune = 'lower'))\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "As stated above, the gradient does not depend on the phase parameter $v_2$; hence, the landscape is flat along lines parallel to the $v_2$-axis."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Optimization"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We choose a simple GradientDescentOptimizer with a step size of 0.1."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "opt = GradientDescentOptimizer(stepsize=0.1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The initial values of the variabels are set to near-zero. This corresponds to an identity gate, in other words, the circuit leaves the photon in the first mode. \n",
    "\n",
    "*Note that at exactly zero the gradient vanishes, and the optimization algorithm will not descend from the starting point. We therefore add some small offsets to avoid this critical point.* "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "var_init = np.array([0.01, 0.01])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We optimize the weights for 100 steps."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Cost after step   0: 0.9998560 | Variables [0.0119999, 0.0100000]\n",
      "Cost after step  10: 0.9945046 | Variables [0.0741993, 0.0100000]\n",
      "Cost after step  20: 0.8206168 | Variables [0.4373458, 0.0100000]\n",
      "Cost after step  30: 0.0723227 | Variables [1.2985156, 0.0100000]\n",
      "Cost after step  40: 0.0009153 | Variables [1.5405375, 0.0100000]\n",
      "Cost after step  50: 0.0000106 | Variables [1.5675459, 0.0100000]\n",
      "Cost after step  60: 0.0000001 | Variables [1.5704473, 0.0100000]\n",
      "Cost after step  70: 0.0000000 | Variables [1.5707589, 0.0100000]\n",
      "Cost after step  80: 0.0000000 | Variables [1.5707923, 0.0100000]\n",
      "Cost after step  90: 0.0000000 | Variables [1.5707959, 0.0100000]\n"
     ]
    }
   ],
   "source": [
    "var = var_init\n",
    "var_gd = []\n",
    "\n",
    "for iteration in range(100):\n",
    "    var = opt.step(objective, var)\n",
    "    var_gd.append(var)\n",
    "    \n",
    "    if iteration % 10 == 0:\n",
    "        print('Cost after step {:3d}: {:0.7f} | Variables [{:0.7f}, {:0.7f}]'\n",
    "              ''.format(iteration, objective(var), var[0], var[1]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Starting at a different offset, we train the MomentumOptimizer, which improves on gradient descent by making each update dependent on the previous gradient, like how a ball rolling down a hill accumulates momentum."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Cost after step   0: 0.9998560 | Variables [0.0119999, 0.5000000]\n",
      "Cost after step  10: 0.9657205 | Variables [0.1862217, 0.5000000]\n",
      "Cost after step  20: 0.0055535 | Variables [1.4962052, 0.5000000]\n",
      "Cost after step  30: 0.0000064 | Variables [1.5682634, 0.5000000]\n",
      "Cost after step  40: 0.0000000 | Variables [1.5709673, 0.5000000]\n",
      "Cost after step  50: 0.0000000 | Variables [1.5707922, 0.5000000]\n",
      "Cost after step  60: 0.0000000 | Variables [1.5707963, 0.5000000]\n",
      "Cost after step  70: 0.0000000 | Variables [1.5707963, 0.5000000]\n",
      "Cost after step  80: 0.0000000 | Variables [1.5707963, 0.5000000]\n",
      "Cost after step  90: 0.0000000 | Variables [1.5707963, 0.5000000]\n"
     ]
    }
   ],
   "source": [
    "mm = MomentumOptimizer(stepsize=0.1, momentum=0.5)\n",
    "\n",
    "var_init = np.array([0.01, 0.5])\n",
    "\n",
    "var = var_init\n",
    "var_mm = []\n",
    "\n",
    "for iteration in range(100):\n",
    "    var = mm.step(objective, var)\n",
    "    var_mm.append(var)\n",
    "\n",
    "    if iteration % 10 == 0:\n",
    "        print('Cost after step {:3d}: {:0.7f} | Variables [{:0.7f}, {:0.7f}]'\n",
    "              ''.format(iteration, objective(var), var[0], var[1]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "fig = plt.figure(figsize = (6, 4))\n",
    "ax = fig.gca(projection='3d')\n",
    "\n",
    "X = np.arange(-3.1, 1.6, 0.1)\n",
    "Y = np.arange(-1., 1.25, 0.25)\n",
    "\n",
    "xx, yy = np.meshgrid(X, Y)\n",
    "Z = np.array([[objective([x, y]) for x in X] for y in Y]).reshape(len(Y), len(X))\n",
    "surf = ax.plot_surface(xx, yy, Z, cmap=cm.coolwarm, antialiased=False)\n",
    "\n",
    "path_z = [objective(var)+1e-8 for var in var_gd]\n",
    "path_x = [var[0] for var in var_gd]\n",
    "path_y = [var[1] for var in var_gd]\n",
    "ax.plot(path_x, path_y, path_z, c='green', marker='.', label=\"graddesc\")\n",
    "\n",
    "path_z = [objective(var)+1e-8 for var in var_mm]\n",
    "path_x = [var[0] for var in var_mm]\n",
    "path_y = [var[1] for var in var_mm]\n",
    "ax.plot(path_x, path_y, path_z, c='purple', marker='.', label=\"momentum\")\n",
    "\n",
    "ax.set_xlabel(\"v1\")\n",
    "ax.set_ylabel(\"v2\")\n",
    "ax.zaxis.set_major_locator(MaxNLocator(nbins = 5, prune = 'lower'))\n",
    "ax.yaxis.set_major_locator(MaxNLocator(nbins = 4, prune = 'lower'))\n",
    "\n",
    "plt.legend()\n",
    "plt.show()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
